package com.semidata.trp.monitor.report;

import java.io.File;
import java.io.FileInputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

import com.google.common.util.concurrent.AtomicDouble;
import com.semidata.rtd.core.log.Logger;
import com.semidata.trp.message.business.Report;
import com.semidata.trp.monitor.config.Config;

public class ReportData {

	private String server;
	// private ConcurrentMap<Integer, AtomicDouble> organizationCosts = new
	// ConcurrentHashMap<>();
	private ConcurrentMap<Integer, ConcurrentMap<Integer, AtomicDouble>> organizationCosts = new ConcurrentHashMap<>();
	private ConcurrentMap<Integer, ConcurrentMap<Integer, AtomicDouble>> strategyCosts = new ConcurrentHashMap<>();
	private ConcurrentMap<Integer, ConcurrentMap<Integer, AtomicLong>> strategyImpressions = new ConcurrentHashMap<>();
	private ConcurrentMap<Integer, AtomicLong> strategyClicks = new ConcurrentHashMap<>();
	private ConcurrentMap<Integer, AtomicLong> resourceImpressions = new ConcurrentHashMap<>();
	private ConcurrentMap<Integer, AtomicLong> resourceClicks = new ConcurrentHashMap<>();

	private ConcurrentMap<String, AtomicBoolean> keyWordList = new ConcurrentHashMap<>();

	public ReportData() {
		server = Config.getConfig().getMonitorId();
	}

	public void load(File file) throws Exception {

		try {
			Report.MonitorReport report = Report.MonitorReport
					.parseFrom(new FileInputStream(file));

			server = report.getServer();
			Config config = Config.getConfig();
			if (!config.getMonitorId().equals(server))
				throw new Exception("bad server id");

			for (Report.OrganizationCost item : report
					.getOrganizationCostList()) {
				// organizationCosts.put(item.getOrganization(), new
				// AtomicDouble(item.getCost()));
				ConcurrentMap<Integer, AtomicDouble> mediaType = organizationCosts
						.get(item.getOrganization());
				if(mediaType == null){
					mediaType = new ConcurrentHashMap<>();
				}
				mediaType.putIfAbsent(0, new AtomicDouble(item.getCostIn()));
				mediaType.putIfAbsent(1, new AtomicDouble(item.getCostOut()));
				mediaType.putIfAbsent(2, new AtomicDouble(item.getCostAlly()));
				organizationCosts
						.putIfAbsent(item.getOrganization(), mediaType);
			}

			for (Report.StrategyCost item : report.getStrategyCostList()) {
				// strategyCosts.put(item.getStrategy(),new
				// AtomicDouble(item.getCost()));
				ConcurrentMap<Integer, AtomicDouble> mediaType = strategyCosts
						.get(item.getStrategy());
				if(mediaType == null){
					mediaType = new ConcurrentHashMap<>();
				}
				mediaType.putIfAbsent(0, new AtomicDouble(item.getCostIn()));
				mediaType.putIfAbsent(1, new AtomicDouble(item.getCostOut()));
				mediaType.putIfAbsent(2, new AtomicDouble(item.getCostAlly()));
				strategyCosts.putIfAbsent(item.getStrategy(), mediaType);
			}

			for (Report.StrategyImpression item : report
					.getStrategyImpressionList()) {
				ConcurrentMap<Integer, AtomicLong> mediaType = strategyImpressions
						.get(item.getStrategy());
				if(mediaType == null){
					mediaType = new ConcurrentHashMap<>();
				}
				mediaType
						.putIfAbsent(0, new AtomicLong(item.getImpressionIn()));
				mediaType.putIfAbsent(1,
						new AtomicLong(item.getImpressionOut()));
				mediaType.putIfAbsent(2,
						new AtomicLong(item.getImpressionAlly()));
				strategyImpressions.putIfAbsent(item.getStrategy(), mediaType);
			}

			for (Report.StrategyClick item : report.getStrategyClickList()) {
				strategyClicks.put(item.getStrategy(),
						new AtomicLong(item.getClick()));
			}

			for (Report.ResourceImpression item : report
					.getResourceImpressionList()) {
				resourceImpressions.put(item.getResource(),
						new AtomicLong(item.getImpression()));
			}

			for (Report.ResourceClick item : report.getResourceClickList()) {
				resourceClicks.put(item.getResource(),
						new AtomicLong(item.getClick()));
			}

			for (Report.KeyWordList item : report.getKeywordList()) {
				keyWordList.put(item.getKeyword1() + "_" + item.getKeyword2()
						+ "_" + item.getKeyword3(), new AtomicBoolean(true));
			}

		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}

	}

	public Report.MonitorReport dump() {

		Report.MonitorReport.Builder builder = Report.MonitorReport
				.newBuilder();

		for (Map.Entry<Integer, ConcurrentMap<Integer, AtomicDouble>> entry : organizationCosts
				.entrySet()) {
			Report.OrganizationCost.Builder b = Report.OrganizationCost
					.newBuilder();
			ConcurrentMap<Integer, AtomicDouble> mediaType = entry.getValue();
			b.setOrganization(entry.getKey());
			if (mediaType.get(0) != null) {
				b.setCostIn(mediaType.get(0).doubleValue());
			} else {
				b.setCostIn(0.0);
			}
			if (mediaType.get(1) != null) {
				b.setCostOut(mediaType.get(1).doubleValue());
			} else {
				b.setCostOut(0.0);
			}
			if (mediaType.get(2) != null) {
				b.setCostAlly(mediaType.get(2).doubleValue());
			} else {
				b.setCostAlly(0.0);
			}
			builder.addOrganizationCost(b.build());
		}

		for (Map.Entry<Integer, ConcurrentMap<Integer, AtomicDouble>> entry : strategyCosts
				.entrySet()) {
			Report.StrategyCost.Builder b = Report.StrategyCost.newBuilder();
			b.setStrategy(entry.getKey());
			ConcurrentMap<Integer, AtomicDouble> media = entry.getValue();
			if (media.get(0) != null) {
				b.setCostIn(media.get(0).doubleValue());
			} else {
				b.setCostIn(0.0);
			}
			if (media.get(1) != null) {
				b.setCostOut(media.get(1).doubleValue());
			} else {
				b.setCostOut(0.0);
			}
			if (media.get(2) != null) {
				b.setCostAlly(media.get(2).doubleValue());
			} else {
				b.setCostAlly(0.0);
			}
			builder.addStrategyCost(b.build());
		}

		for (Map.Entry<Integer, ConcurrentMap<Integer, AtomicLong>> entry : strategyImpressions
				.entrySet()) {
			Report.StrategyImpression.Builder b = Report.StrategyImpression
					.newBuilder();
			b.setStrategy(entry.getKey());
			ConcurrentMap<Integer, AtomicLong> media = entry.getValue();
			if (media.get(0) != null) {
				b.setImpressionIn(media.get(0).longValue());
			} else {
				b.setImpressionIn(0);
			}
			if (media.get(1) != null) {
				b.setImpressionOut(media.get(1).longValue());
			} else {
				b.setImpressionOut(0);
			}
			if (media.get(2) != null) {
				b.setImpressionAlly(media.get(2).longValue());
			} else {
				b.setImpressionAlly(0);
			}
			builder.addStrategyImpression(b.build());
		}

		for (Map.Entry<Integer, AtomicLong> entry : strategyClicks.entrySet()) {
			Report.StrategyClick.Builder b = Report.StrategyClick.newBuilder();
			b.setStrategy(entry.getKey());
			b.setClick(entry.getValue().intValue());
			builder.addStrategyClick(b.build());
		}

		for (Map.Entry<Integer, AtomicLong> entry : resourceImpressions
				.entrySet()) {
			Report.ResourceImpression.Builder b = Report.ResourceImpression
					.newBuilder();
			b.setResource(entry.getKey());
			b.setImpression(entry.getValue().intValue());
			builder.addResourceImpression(b.build());
		}

		for (Map.Entry<Integer, AtomicLong> entry : resourceClicks.entrySet()) {
			Report.ResourceClick.Builder b = Report.ResourceClick.newBuilder();
			b.setResource(entry.getKey());
			b.setClick(entry.getValue().intValue());
			builder.addResourceClick(b.build());
		}

		for (Map.Entry<String, AtomicBoolean> entry : keyWordList.entrySet()) {
			Report.KeyWordList.Builder b = Report.KeyWordList.newBuilder();
			String[] kw = new String[3];
			kw = entry.getKey().split("_", 3);
			b.setKeyword1(kw[0]);
			b.setKeyword2(kw[1]);
			b.setKeyword3(kw[2]);
			builder.addKeyword(b.build());
		}
		// keyWordList.clear();

		builder.setServer(server);
		builder.setTime(System.currentTimeMillis());
		return builder.build();

	}

	public void updateOrganizationCosts(int orgId, int mediaType, double value) {
		ConcurrentMap<Integer, AtomicDouble> media = organizationCosts
				.get(orgId);
		if (media == null) {
			organizationCosts.putIfAbsent(orgId,
					new ConcurrentHashMap<Integer, AtomicDouble>());
			media = organizationCosts.get(orgId);
		}
		AtomicDouble obj = media.get(mediaType);
		if (obj == null) {
			media.putIfAbsent(mediaType, new AtomicDouble(0));
			obj = media.get(mediaType);
		}
		// organizationCosts.get(orgId).get(mediaType).addAndGet(value);
		obj.addAndGet(value);
		/*
		 * AtomicDouble obj = organizationCosts.get(id);
		 * 
		 * if (obj == null) { organizationCosts.putIfAbsent(id, new
		 * AtomicDouble(0)); obj = organizationCosts.get(id); }
		 * obj.addAndGet(value);
		 */
	}

	public void updateStrategyCosts(int id, int mediaType, double value) {
		ConcurrentMap<Integer, AtomicDouble> media = strategyCosts.get(id);
		if (media == null) {
			strategyCosts.putIfAbsent(id,
					new ConcurrentHashMap<Integer, AtomicDouble>());
			media = strategyCosts.get(id);
		}
		AtomicDouble obj = media.get(mediaType);
		if (obj == null) {
			media.putIfAbsent(mediaType, new AtomicDouble(0));
			obj = media.get(mediaType);
		}
		obj.addAndGet(value);
		/*
		 * AtomicDouble obj = strategyCosts.get(id);
		 * 
		 * if (obj == null) { strategyCosts.putIfAbsent(id, new
		 * AtomicDouble(0)); obj = strategyCosts.get(id); }
		 * obj.addAndGet(value);
		 */
	}

	public void updateStrategyImpressions(int id, int mediaType, long value) {
		ConcurrentMap<Integer, AtomicLong> media = strategyImpressions.get(id);
		if (media == null) {
			strategyImpressions.putIfAbsent(id,
					new ConcurrentHashMap<Integer, AtomicLong>());
			media = strategyImpressions.get(id);
		}
		AtomicLong obj = media.get(mediaType);
		if (obj == null) {
			media.putIfAbsent(mediaType, new AtomicLong(0));
			obj = media.get(mediaType);
		}
		obj.addAndGet(value);
		/*
		 * AtomicLong obj = strategyImpressions.get(id);
		 * 
		 * if (obj == null) { strategyImpressions.putIfAbsent(id, new
		 * AtomicLong(0)); obj = strategyImpressions.get(id); }
		 * obj.addAndGet(value);
		 */
	}

	public void updateStrategyClicks(int id, long value) {
		AtomicLong obj = strategyClicks.get(id);

		if (obj == null) {
			strategyClicks.putIfAbsent(id, new AtomicLong(0));
			obj = strategyClicks.get(id);
		}
		obj.addAndGet(value);
	}

	public void updateResourceImpressions(int id, long value) {
		AtomicLong obj = resourceImpressions.get(id);

		if (obj == null) {
			resourceImpressions.putIfAbsent(id, new AtomicLong(0));
			obj = resourceImpressions.get(id);
		}
		obj.addAndGet(value);
	}

	public void updateResourceClicks(int id, long value) {
		AtomicLong obj = resourceClicks.get(id);

		if (obj == null) {
			resourceClicks.putIfAbsent(id, new AtomicLong(0));
			obj = resourceClicks.get(id);
		}
		obj.addAndGet(value);
	}

	public void updateKeyWordList(String kw) {
		AtomicBoolean obj = keyWordList.get(kw);

		if (obj == null) {
			keyWordList.putIfAbsent(kw, new AtomicBoolean(true));
			obj = keyWordList.get(kw);
		}
		obj.getAndSet(true);
	}

	public ConcurrentMap<Integer, ConcurrentMap<Integer, AtomicDouble>> getOrganizationCosts() {
		return organizationCosts;
	}

	public ConcurrentMap<Integer, ConcurrentMap<Integer, AtomicDouble>> getStrategyCosts() {
		return strategyCosts;
	}

	public ConcurrentMap<Integer, ConcurrentMap<Integer, AtomicLong>> getStrategyImpressions() {
		return strategyImpressions;
	}

	public ConcurrentMap<Integer, AtomicLong> getStrategyClicks() {
		return strategyClicks;
	}

	public ConcurrentMap<Integer, AtomicLong> getResourceImpressions() {
		return resourceImpressions;
	}

	public ConcurrentMap<Integer, AtomicLong> getResourceClicks() {
		return resourceClicks;
	}

	public ConcurrentMap<String, AtomicBoolean> getKeyWordList() {
		return keyWordList;
	}

}
